﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Lypshare.Net
{
	/// <summary>
	/// Packet stream.
	/// </summary>
	/// <exception cref='ArgumentNullException'>
	/// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> .
	/// </exception>
	/// <exception cref='ArgumentException'>
	/// Is thrown when an argument passed to a method is invalid.
	/// </exception>
	/// <exception cref='NotImplementedException'>
	/// Is thrown when a requested operation is not implemented for a given type.
	/// </exception>
    public class PacketStream : Stream
    {
        // --------------------------------------------------------
        // Class Variables
        // --------------------------------------------------------


        /// <summary>
        /// The _data.
        /// </summary>
        private List<byte> _data = new List<byte>();


        // --------------------------------------------------------
        // Class Properties
        // --------------------------------------------------------


        /// <summary>
        /// Gets the data.
        /// </summary>
        /// <value>
        /// The data.
        /// </value>
        public byte[] Data
        {
            get { return _data.ToArray(); }

        } // Property: Data


        /// <summary>
        /// Gets the length.
        /// </summary>
        /// <value>
        /// The length.
        /// </value>
        public override long Length
        {
            get { return _data.Count; }

        } // Property: Length


        /// <summary>
        /// Gets or sets the position.
        /// </summary>
        /// <value>
        /// The position.
        /// </value>
        public override long Position
        {
            get { return 0; }
            set { }

        } // Property: Position


        /// <summary>
        /// Gets a value indicating whether this instance can write.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance can write; otherwise, <c>false</c>.
        /// </value>
        public override bool CanWrite
        {
            get { return true; }

        } // Property: CanWrite


        /// <summary>
        /// Gets a value indicating whether this instance can read.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance can read; otherwise, <c>false</c>.
        /// </value>
        public override bool CanRead
        {
            get { return true; }

        } // Property: CanRead


        /// <summary>
        /// Gets a value indicating whether this instance can seek.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance can seek; otherwise, <c>false</c>.
        /// </value>
        public override bool CanSeek
        {
            get { return false; }

        } // Property: CanSeek


        // --------------------------------------------------------
        // Class Functions
        // --------------------------------------------------------



        /// <summary>
        /// Write the specified buffer, offset and count.
        /// </summary>
        /// <param name='buffer'>
        /// Buffer.
        /// </param>
        /// <param name='offset'>
        /// Offset.
        /// </param>
        /// <param name='count'>
        /// Count.
        /// </param>
        /// <exception cref='ArgumentNullException'>
        /// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> .
        /// </exception>
        /// <exception cref='ArgumentException'>
        /// Is thrown when an argument passed to a method is invalid.
        /// </exception>
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (buffer == null) 
                throw new ArgumentNullException("buffer");

            if (buffer.Length - offset < count) 
                throw new ArgumentException("Buffer musst equal or larger than count");

            _data.AddRange(buffer.Skip(offset).Take(count));

        } // Write


        /// <summary>
        /// Read the specified buffer, offset and count.
        /// </summary>
        /// <param name='buffer'>
        /// Buffer.
        /// </param>
        /// <param name='offset'>
        /// Offset.
        /// </param>
        /// <param name='count'>
        /// Count.
        /// </param>
        /// <exception cref='ArgumentNullException'>
        /// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> .
        /// </exception>
        /// <exception cref='ArgumentException'>
        /// Is thrown when an argument passed to a method is invalid.
        /// </exception>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (buffer == null) 
                throw new ArgumentNullException("buffer");

            if (Length < count) 
                throw new ArgumentException("Stream must equal or larger than count");

            if (buffer.Length - offset < count) 
                throw new ArgumentException("Buffer musst equal or larger than count");

            _data.CopyTo(0, buffer, offset, count);
            _data.RemoveRange(0, count);

            return count;

        } // Read


        /// <summary>
        /// Sets the length.
        /// </summary>
        /// <param name='value'>
        /// Value.
        /// </param>
        /// <exception cref='NotImplementedException'>
        /// Is thrown when a requested operation is not implemented for a given type.
        /// </exception>
        public override void SetLength(long value)
        {
            throw new NotImplementedException();

        } // SetLength


        /// <summary>
        /// Seek the specified offset and origin.
        /// </summary>
        /// <param name='offset'>
        /// Offset.
        /// </param>
        /// <param name='origin'>
        /// Origin.
        /// </param>
        /// <exception cref='NotImplementedException'>
        /// Is thrown when a requested operation is not implemented for a given type.
        /// </exception>
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();

        } // Seek


        /// <summary>
        /// Flush this instance.
        /// </summary>
        /// <exception cref='NotImplementedException'>
        /// Is thrown when a requested operation is not implemented for a given type.
        /// </exception>
        public override void Flush()
        {
            throw new NotImplementedException();

        } // Flush

    } // class PacketStream
} // namespace Lypshare.Net